﻿using System;
using System.Collections.Generic;
using System.Text;
using FeedDotNet.Common;
using FeedDotNet;
using System.Text.RegularExpressions;
using System.Globalization;
using System.Net;
using System.Xml;
using System.IO;
using System.Collections;

namespace ConsoleApplication
{
    static class ProcessFeeds
    {
        public static void parseMovieInfoFromRSSTitle(MovieFeedItem movieItem)
        {
            movieItem.Title = parseTitle(movieItem.feedTitle);
            movieItem.year = parseYear(movieItem.feedTitle);
            movieItem.resolution = parseResolution(movieItem.feedTitle);
        }

        public static string parseTitle(String dirty)
        {
            string clean = removeSpecialChars(dirty);
            if (clean.Contains(".x264"))
                clean = clean.Substring(0, clean.IndexOf(".x264"));
            clean += ".";
            clean = "." + clean;
            if(clean.Contains(".german.") || clean.Contains(".nl.") || clean.Contains(".nlsubs.")) {
                return "";
            }

            clean = clean.Replace(".req.", ".");
            clean = clean.Replace(".bd9.", ".");
            clean = clean.Replace(".dd2.", ".");
            clean = clean.Replace(".limited.", ".");
            clean = clean.Replace(".nl.", ".");
            clean = clean.Replace(".real.repack.", ".");
            clean = clean.Replace(".repack.", ".");
            clean = clean.Replace(".proper.", ".");
            clean = clean.Replace(".bluray.", ".");
            clean = clean.Replace(".blu.ray.", ".");
            clean = clean.Replace(".german.", ".");
            clean = clean.Replace(".uncut.", ".");
            clean = clean.Replace(".unrated.", ".");
            clean = clean.Replace(".clean.audio.", ".");
            clean = clean.Replace(".version.", ".");
            clean = clean.Replace(".subfix.", ".");
            clean = clean.Replace(".subs.", ".");
            clean = clean.Replace(".commonsense.", ".");
            clean = clean.Replace(".dubbed.", ".");
            clean = clean.Replace(".dubs.", ".");
            clean = clean.Replace(".dub.", ".");
            clean = clean.Replace(".dubbed.", ".");
            clean = clean.Replace(".dl.", ".");
            clean = clean.Replace(".directors.cut.", ".");
            clean = clean.Replace(".extended.cut.", ".");
            clean = clean.Replace(".extended.", ".");
            clean = clean.Replace(".dts.", ".");
            clean = clean.Replace(".ac3.", ".");
            clean = clean.Replace(".hdtv.", ".");
            
            if (clean.StartsWith("."))
                clean = clean.Remove(0,1);
            clean = removeSpecialChars(clean);
            Regex regex = new Regex("(.*)(1080p|720p).*");
            Match match = regex.Match(clean);
            if (match.Groups.Count > 2)
                clean = match.Groups[1].Value;

            clean = removeSpecialChars(clean);
            regex = new Regex("(.*)([12][09][0-9][0-9]).*");
            match = regex.Match(clean);
            if (match.Groups.Count > 2)
                clean = match.Groups[1].Value;

            clean = removeSpecialChars(clean);
            clean = CultureInfo.CurrentCulture.TextInfo.ToTitleCase(clean);
            return clean;
        }

        public static string parseResolution(String dirty)
        {
            string clean = removeSpecialChars(dirty);
            Regex regex = new Regex(".*(1080p|720p).*");
            Match match = regex.Match(clean);
            if (match.Groups.Count > 1)
            {
                return match.Groups[match.Groups.Count - 1].Value;
            }
            else
                return "";
        }

        private static string parseYear(String dirty)
        {
            string clean = removeSpecialChars(dirty);
            clean = clean.Replace("1080p", "");
            clean = clean.Replace("720p", "");
            Regex regex = new Regex(".*(20[0-9][0-9]|19[0-9][0-9]).*");
            Match match = regex.Match(clean);
            if (match.Groups.Count > 1)
            {
              return match.Groups[match.Groups.Count - 1].Value;
            }
            else
                return "";

        }

        public static String ScrapeNZB(MovieFeedItem movie)
        {
            String html = "";
            html = System.Text.Encoding.UTF8.GetString(
                requestURL(
                    string.Format("http://nzbindex.com/rss/?q={0}&g[]=16&g[]=122&g[]=553&g[]=636&sort=agedesc&minsize=2000&nfo=%22{1}%22+-nl+-german&max=5&more=1",
                        System.Web.HttpUtility.UrlEncode(movie.resolution.Replace("p", "")), 
                        System.Web.HttpUtility.UrlEncode( movie.Title.Replace('.', '+'))
                    )
                )
            );
            return html;
        }

        public static MovieFeedItem setMovieDBInfo(MovieFeedItem movie)
        {
            if (movie.imdbID == "")
                return movie;

            string movieXMLString;

            try
            {
                movieXMLString = System.Text.Encoding.UTF8.GetString(requestURL("http://imdb.com/title/tt" + movie.imdbID));
            }
            catch (Exception e)
            {
                return movie;
            }
            
            // Try one more time if you dont get anything

            if (movieXMLString == "")
            {
                Console.WriteLine("Could not retrive IMDB Info");
                return movie;
            }
            
            movieXMLString = movieXMLString.Replace('\n', ' ');

            Regex regex;
            Match match;

            //Title
            //Regex regex = new Regex(@"<h1>([^<]*)");
            // = regex.Match(movieXMLString).Result("$1");
            
            
            //Director
            regex = new Regex(@"Director:</h5>\s*<[^>]*>\s*<a\s*href=[^\w]*name[^>]*>([^<]*)</a>");
            match = regex.Match(movieXMLString);
            if (match.Success)
                movie.director = match.Result("$1").Trim();

            //Actors
            regex = new Regex(@"<a\s*href=[^\w]*name[^>]*>([^<]*)</a>");
            String actorHTML = "";
            if(movieXMLString.Contains("<h3>Cast</h3>"))
                actorHTML = movieXMLString.Substring(movieXMLString.IndexOf("<h3>Cast</h3>"));
            if (actorHTML.Contains("<form"))
                actorHTML = actorHTML.Substring(0, actorHTML.IndexOf("<form"));
            else
                actorHTML = "";
            MatchCollection matches = regex.Matches(actorHTML);
            ArrayList actors = new ArrayList();
            foreach (Match actor in matches)
            {
                actors.Add(actor.Result("$1").Trim());
            }
            movie.actors = actors;

            //Year
            if (movie.year == "")
            {
                regex = new Regex(@"/Sections/Years/([0-9]*)");
                match = regex.Match(movieXMLString);
                if (match.Success)
                    movie.year = match.Result("$1").Trim();
            }
            //Rating / Votes
            regex = new Regex(@"<b>([0-9.]+/10)</b>[^<]*<a href=""ratings"" class=""tn15more"">([0-9,]+) votes</a>");
            match = regex.Match(movieXMLString);
            if (match.Success)
                movie.rating = match.Result("$1 with $2 votes").Trim();

            //Runtime
            regex = new Regex(@"<h5>Runtime:</h5>[^0-9]*([^<]*)");
            match = regex.Match(movieXMLString);
            if (match.Success)
            {
                String dirtyTime = match.Result("$1").Trim();
                if (dirtyTime.Contains("min"))
                    dirtyTime = dirtyTime.Substring(0, dirtyTime.IndexOf("min") + 3);
                movie.runTime = dirtyTime;
            }
            
            //Genres
            regex = new Regex(@"""/Sections/Genres/[^/]*/"">([^<]*)</a>");
            matches = regex.Matches(movieXMLString);
            String genres = "";
            foreach (Match genre in matches)
            {
                genres += genre.Result("$1 ");
            }
            movie.genre = genres.Trim();

            //MPAA
            regex = new Regex(@"MPAA</a>:</h5>\s*<div class=[^\w]*info-content[^>]*>\s*Rated\s*(.[^ ]*)");
            match = regex.Match(movieXMLString);
            if (match.Success)
                movie.mpaa = match.Result("$1").Trim();

            //Plot
            regex = new Regex(@"Plot:</h5>(?:[^>]*>)?\s*([^<]*)<a class=""tn15more");
            match = regex.Match(movieXMLString);
            if (match.Success)
                movie.plot = match.Result("$1").Trim();
            
            
            return movie;
        }

        public static string getImdbID(String title)
        {
            string imdbID = "";
            string jsonData = null;
            jsonData = System.Text.Encoding.UTF8.GetString(
                requestURL("http://ajax.googleapis.com/ajax/services/search/web?v=1.0&rsz=small&q=site:imdb.com/title+" + System.Web.HttpUtility.UrlEncode(title)));
            
            Regex regex = new Regex("imdb.com/title/tt([0-9]{7})");
            Match match = regex.Match(jsonData);
            if (match.Groups.Count >= 2)
                imdbID = match.Groups[1].Value;
            else
                Console.WriteLine("http://ajax.googleapis.com/ajax/services/search/web?v=1.0&rsz=small&q=site:imdb.com/title+" + System.Web.HttpUtility.UrlEncode(title));
            if (imdbID.Length == 7)
            {
                return imdbID;
            }
            else
            {
                return "";
            }
        }

        private static void FAIL_IF(bool b, string s)
        {
            if (b)
            {
                Console.WriteLine(s);
                throw new Exception("failed");
            }
        }

        private static string removeSpecialChars(String dirty) {
            String clean = dirty;
            clean = clean.ToLower();
            clean = clean.Replace(" ", ".");
            clean = clean.Replace("_", ".");
            clean = clean.Replace("(", ".");
            clean = clean.Replace(",", ".");
            clean = clean.Replace(")", ".");
            clean = clean.Replace("[", ".");
            clean = clean.Replace("]", ".");
            clean = clean.Replace(":", ".");
            clean = clean.Replace("'", "");
            clean = clean.Replace("-", ".");
            clean = clean.Replace("?", ".");
            clean = clean.Replace("!", ".");
            clean = clean.Replace("@", ".");
            clean = clean.Replace("/", ".");
            clean = clean.Replace("\\", ".");
            clean = clean.Replace("{", ".");
            clean = clean.Replace("}", ".");
            clean = clean.Replace("+", ".");

            while (clean.Contains(".."))
            {
                clean = clean.Replace("..", ".");
            }
            if (clean.StartsWith("."))
                clean = clean.Substring(1);
            if (clean.EndsWith("."))
                clean = clean.Substring(0, clean.Length - 1);
            return clean;
        }

        // Single Request
        public static byte[] requestURL(String url)
        {
            int retryCount = 3;

            while (retryCount > 0)
            {
                try
                {
                    HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(url);
                    request.AllowAutoRedirect = true;
                    request.ReadWriteTimeout = 6000;
                    request.Timeout = 6000;
                    request.UserAgent = "Mozilla 6.0/RSS Awesome";
                    request.Referer = url;
                    request.Accept = "*/*";

                    using (WebResponse wr = request.GetResponse())
                    {
                        using (Stream responseStream = wr.GetResponseStream())
                        {
                            using (MemoryStream ms = new MemoryStream(100 * 1024))
                            {
                                int spot = 0, cnt = 0;
                                byte[] buffer = new byte[10*1024];
                                do
                                {
                                    cnt = responseStream.Read(buffer, 0, buffer.Length);
                                    ms.Write(buffer, 0, cnt);
                                    spot += cnt;
                                }
                                while (cnt != 0);
                                return ms.ToArray();
                            }
                        }
                    }
                }
                catch (Exception e)
                {
                    Console.WriteLine("when requesting " + url);
                    Console.WriteLine(e.ToString());
                    retryCount--;
                    if (retryCount > 0)
                        Console.WriteLine("retrying request");
                    System.Threading.Thread.Sleep(1000);
                    continue;
                }
            }

            return null;
        }

        // Single Request
        public static bool requestURLExits(String url)
        {
            try
            {
                HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(url);
                request.Method = "HEAD";
                request.AllowAutoRedirect = true;
                request.ReadWriteTimeout = 6000;
                request.Timeout = 6000;
                request.UserAgent = "Mozilla 6.0/RSS Awesome";
                request.Referer = url;
                request.Accept = "*/*";

                using (HttpWebResponse wr = (HttpWebResponse)request.GetResponse())
                {
                    if (wr.StatusDescription == "OK")
                        return true;
                    else
                        return false;
                }
            }
            catch (Exception e)
            {
                return false;
            }
        }

            
        

        public static byte[] getImageByteStream(String url)
        {
            byte[] imageData = null;
            try
            {
                imageData = requestURL(url);
            }
            catch (Exception e)
            {
                Console.WriteLine("Cannot request the page... " + url);
                Console.WriteLine(e.ToString());
            }
            return imageData;
        }

        public static void prepItemForPost(MovieFeedItem movieFeedItem)
        {
            movieFeedItem.Content = "<table border=\"0\" width=\"100%\" cellpadding=\"10\"><tr><td width=\"1%\" valign=\"top\">" +
                                    "<img src=\"" + movieFeedItem.imageURL + "\" align=\"middle\" /></td>" +
                                    "<td width=\"99%\" valign=\"top\">" +
                                    "<b>Title:</b> " + movieFeedItem.Title + "<br />" +
                                    "<b>Year:</b> " + movieFeedItem.year + "<br />" +
                                    "<b>MPAA:</b> " + movieFeedItem.mpaa + "<br />" +
                                    "<b>Run Time:</b> " + movieFeedItem.runTime + "<br />" +
                                    "<b>Rating:</b> " + movieFeedItem.rating + "<br />" +
                                    "<b>Resolution:</b> " + movieFeedItem.resolution + "<br />" +
                                    "<b>IMDB:</b> <a href=\"http://imdb.com/title/tt" + movieFeedItem.imdbID + "\">IMDB Link</a><br />" +
                                    "<b>Plot:</b> " + movieFeedItem.plot + "<br />" +
                                    "<b>Director:</b> " + movieFeedItem.director + "<br />" +
                                    "<b>Genre:</b> " + movieFeedItem.genre + "<br />" + "<br />" +
                                    string.Format("<b>Actors:</b> {0}{1}{2}{3}{4}",
                                        (movieFeedItem.actors.Count > 0) ? movieFeedItem.actors[0] : string.Empty,
                                        (movieFeedItem.actors.Count > 1) ? " | " + movieFeedItem.actors[1] : string.Empty,
                                        (movieFeedItem.actors.Count > 2) ? " | " + movieFeedItem.actors[2] : string.Empty,
                                        (movieFeedItem.actors.Count > 3) ? " | " + movieFeedItem.actors[3] : string.Empty,
                                        (movieFeedItem.actors.Count > 4) ? " | " + movieFeedItem.actors[4] : string.Empty) + "<br/>"+
                                    "<b>Release Info:</b> " + movieFeedItem.feedTitle + "<br />" + 
                                    movieFeedItem.ContentOrSummary +
                                    "</td></tr></table>";
        }
    }
}
